import {
  Entity,
  BaseEntity,
  PrimaryGeneratedColumn,
  Column,
  CreateDateColumn,
  UpdateDateColumn,
  BeforeInsert,
} from "typeorm";
import { Exclude, Expose } from "class-transformer";
import { NodeAuth } from "node-auth0";
import * as jwt from "jsonwebtoken";

@Entity("users")
export class UsersEntity extends BaseEntity {
  @Exclude()
  private nodeAuth: NodeAuth;
  constructor() {
    super();
    this.nodeAuth = new NodeAuth();
  }

  @PrimaryGeneratedColumn({
    type: "int",
    name: "id",
    comment: "主键id",
  })
  id: number;

  // @Column('varchar', {
  //   nullable: false,
  //   primary: true,
  //   generated: 'uuid',
  //   length: 50,
  //   name: 'uuid',
  //   comment: 'uuid',
  // })
  // uuid: string;

  @Column({
    type: "varchar",
    nullable: false,
    length: 50,
    unique: true,
    name: "username",
    comment: "用户名",
  })
  username: string;

  @Exclude() // 排除返回字段，不返回给前端
  @Column({
    type: "varchar",
    nullable: false,
    length: 100,
    comment: "密码",
  })
  password: string;

  // 根据现有字段生成新字段
  @Expose()
  isDelStr(): string {
    return this.isDel ? "删除" : "正常";
  }

  @Column("tinyint", {
    nullable: false,
    default: () => 0,
    name: "is_del",
    comment: "是否删除,1表示删除,0表示正常",
  })
  isDel: number;

  @CreateDateColumn({
    type: "timestamp",
    nullable: false,
    name: "created_at",
    comment: "创建时间",
  })
  createdAt: Date;

  @UpdateDateColumn({
    type: "timestamp",
    nullable: false,
    name: "updated_at",
    comment: "更新时间",
  })
  updateAt: Date;

  @BeforeInsert()
  makePassword(): void {
    // 插入数据库前，对明文密码进行加密
    this.password = this.nodeAuth.makePassword(this.password);
  }

  @Expose()
  private get token() {
    const { id, username } = this;
    // 生成签名
    // 要签名的内容， 加盐秘钥，过期时间
    return jwt.sign({ id, username }, process.env.SECRET, { expiresIn: "7d" });
  }

  /**
   * 返回用户信息
   * @param isShowToken 是否显示token
   */
  public toResponseObject(isShowToken = true): { [k: string]: any } {
    const { nodeAuth, password, token, username, ...params } = this;
    const responseData = {
      username,
      ...params,
    };
    if (isShowToken) {
      return Object.assign(responseData, { token });
    } else {
      return responseData;
    }
  }
}
